<template>
    <a-tree class="a-menu" :size="props.size" :items="props.items" :getItemsFunc="props.getItemsFunc" :getKeyFunc="props.getNameFunc" :getIsFolderFunc="props.getIsFolderFunc" :getIsItemOpenedFunc="methods.isItemOpened">
        <template v-slot:foldName="{ item, depth, opened }: any">
            <div class="c-f-h c-f-start-center">
                <div class="c-f-h c-f-start-center">
                    <div :class="`c-square-${props.size}`" v-for="n in depth" :key="n"></div>
                </div>
                <a-button class="c-f-h c-f-between-center" :color="props.color" :size="props.size" :block="true" :sharp="true" :plain="true" @click="
                    emit('item-click', item)
                emit('fold-click', item)
                methods.toggleItem(item);
                ">
                    <span>{{ props.getNameFunc(item) }}</span>
                    <span class="fa fa-fw fa-angle-right" v-if="!opened"></span>
                    <span class="fa fa-fw fa-angle-down" v-else></span>
                </a-button>
            </div>
        </template>
        <template v-slot:file="{ item, depth }">
            <div class="c-f-h c-f-start-center">
                <div class="c-f-h c-f-start-center">
                    <div :class="`c-square-${props.size}`" v-for="n in depth" :key="n"></div>
                </div>
                <a-button :color="props.color" :size="props.size" :block="true" :sharp="true" :plain="true" align="left" :active="state.currentActiveItem === item" @click="
                    emit('item-click', item)
                emit('file-click', item)
                state.currentActiveItem = item;
                ">
                    {{ props.getNameFunc(item) }}
                </a-button>
            </div>
        </template>
    </a-tree>
</template>

<script setup lang="ts">
import AButton from './AButton.vue'
import ATree from './ATree.vue'
import { ColorType, SizeType } from '@/types'
import { reactive } from 'vue'

interface PropsType {
    color?: ColorType
    size?: SizeType
    items?: any[]
    getItemsFunc?: (a: any) => any[]
    getNameFunc?: (a: any) => string
    getIsFolderFunc?: (a: any) => boolean
}
const props = withDefaults(defineProps<PropsType>(), {
    color: 'default',
    size: 'm',
    items: () => [],
    getItemsFunc: (a: any) => a.items,
    getNameFunc: (a: any) => a.name,
    getIsFolderFunc: (a: any) => a.type === 0,
})

interface StateType {
    openedItemSet: Set<any>
    currentActiveItem?: any
}
const state = reactive<StateType>({
    openedItemSet: new Set(),
    currentActiveItem: undefined
})

const emit = defineEmits<{
    (e: 'item-click', value: any): void
    (e: 'fold-click', value: any): void
    (e: 'file-click', value: any): void
}>()

const methods = {
    toggleItem(item: any) {
        if (methods.isItemOpened(item)) {
            state.openedItemSet.delete(item)
        } else {
            state.openedItemSet.add(item)
        }
    },
    isItemOpened(item: any) {
        return state.openedItemSet.has(item)
    },
    /**
     * 折叠所有
     */
    foldAll() {
        state.openedItemSet.clear()
    },
    /**
     * 主动激活菜单项，会同时打开包含其的文件夹，但是不会触发item-click、fold-click、file-click事件
     */
    activeItem(toActiveItem: any) {
        state.currentActiveItem = toActiveItem
        let toCheckList = [...props.items.map(a => [a, undefined])]
        while (toCheckList.length) {
            let [item, parent] = toCheckList.shift() as [any, any]
            if (item === toActiveItem) {
                parent && state.openedItemSet.add(parent)
                return
            }
            if (item.files) {
                toCheckList.push(...item.files.map((a: any) => [a, item]))
            }
        }
    },
}

defineExpose({
    activeItem: methods.activeItem
})
</script>